package de.schule.barnimgymnasium.autotransporter;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;

public class Lautsprecher {
	public static String sounddir = "/home/uwe.hermann/workspace/transporter/sound";
	String sprecher = "Reiner";
	AudioInputStream ais;
	Map<String, String> text = new HashMap<String, String>(24);
	public static final String HALLO = "Hallo";
	public static final String TSCHUESS = "Tschuess";
	public static final String HOERE_MOTORGERAEUSCHE = "HoereMotorgeraeusche";
	public static final String FARBEN_LERNEN = "FarbenLernen";
	public static final String ROT = "Rot";
	public static final String GELB = "Gelb";
	public static final String GRUEN = "Gruen";
	public static final String BLAU = "Blau";
	public static final String ZAEHLEN_LERNEN = "ZaehlenLernen";
	public static final String EINS = "Eins";
	public static final String ZWEI = "Zwei";
	public static final String DREI = "Drei";
	public static final String VIER = "Vier";
	public static final String SPIELEN = "Spielen";
	public static final String PARKE_ROT = "ParkeRot";
	public static final String PARKE_GELB = "ParkeGelb";
	public static final String PARKE_GRUEN = "ParkeGruen";
	public static final String PARKE_BLAU = "ParkeBlau";
	public static final String RICHTIG = "Richtig";
	public static final String FALSCH_ROT = "FalschRot";
	public static final String FALSCH_GELB = "FalschGelb";
	public static final String FALSCH_GRUEN = "FalschGruen";
	public static final String FALSCH_BLAU = "FalschBlau";
	public static final String HOFFNUNGSLOS = "Hoffnungslos";

	// Clip playClip = null;

	public Lautsprecher() {
		text.put(HALLO, "Hallo kleiner Fahrer.");
		text.put(TSCHUESS, "Tschüss, bis dann auf der Straße.");
		text.put(HOERE_MOTORGERAEUSCHE, "Höre den Motorgeräuschen zu.");
		text.put(FARBEN_LERNEN, "Lass uns Farben lernen.");
		text.put(ROT, "Rot.");
		text.put(GELB, "Gelb.");
		text.put(GRUEN, "Grün.");
		text.put(BLAU, "Blau.");
		text.put(ZAEHLEN_LERNEN, "Lass uns zählen lernen.");
		text.put(EINS, "Eins.");
		text.put(ZWEI, "Zwei.");
		text.put(DREI, "Drei.");
		text.put(VIER, "Vier.");
		text.put(SPIELEN, "Lass uns spielen.");
		text.put(PARKE_ROT, "Parke das rote Auto.");
		text.put(PARKE_GELB, "Parke das gelbe Auto.");
		text.put(PARKE_GRUEN, "Parke das grüne Auto.");
		text.put(PARKE_BLAU, "Parke das blaue Auto.");
		text.put(RICHTIG, "Gut.");
		text.put(FALSCH_ROT, "Oh Oh. Du hast das rote Auto geparkt. Ich sagte:");
		text.put(FALSCH_GELB,
				"Oh Oh. Du hast das gelbe Auto geparkt. Ich sagte:");
		text.put(FALSCH_GRUEN,
				"Oh Oh. Du hast das grüne Auto geparkt. Ich sagte:");
		text.put(FALSCH_BLAU,
				"Oh Oh. Du hast das blaue Auto geparkt. Ich sagte:");
		text.put(HOFFNUNGSLOS, "Frage jemanden um Rat.");
		// Line.Info linfo = new Line.Info(Clip.class);
		// try {
		// Line line = AudioSystem.getLine(linfo);
		// playClip = (Clip) line;
		// } catch (LineUnavailableException e) {
		// e.printStackTrace();
		// }
	}

	public void say(final String key) {
		if (sprecher != null) {
			try {
				String filename = sounddir + "/" + sprecher + "/" + key;
				String[] filetypes = { ".mp3", ".wav" };
				for (String ext : filetypes) {
					File f = new File(filename + ext);

					if (!f.exists()) {
						continue;
					}
					say(new URL("file:///" + f.getAbsolutePath()));
				}
				return;
			} catch (IOException | UnsupportedAudioFileException
					| LineUnavailableException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		System.out.println(text.get(key));
	}

	// public void playUrl(final URL soundfile) {
	//
	// try {
	// if (this.playClip != null) {
	// if (this.playClip.isOpen()) {
	// this.playClip.stop();
	// }
	// }
	// InputStream soundInputStream = soundfile.openStream();
	// playClip.open(AudioSystem.getAudioInputStream(soundInputStream));
	// playClip.start();
	// } catch (UnsupportedAudioFileException e) {
	// // TODO Auto-generated catch block
	// e.printStackTrace();
	// } catch (IOException e) {
	// // TODO Auto-generated catch block
	// e.printStackTrace();
	// } catch (LineUnavailableException e) {
	// // TODO Auto-generated catch block
	// e.printStackTrace();
	// }
	// }
	//
	// public void stop() {
	// if (this.playClip != null && playClip.isOpen()) {
	// this.playClip.stop();
	// this.playClip = null;
	// }
	// }

	public void say(final URL soundfile) throws IOException,
			UnsupportedAudioFileException, LineUnavailableException {
		InputStream soundInputStream = soundfile.openStream();
		ais = AudioSystem.getAudioInputStream(soundInputStream);
		play();

	}

	private void play() throws IOException, LineUnavailableException {

		try {
			AudioFormat baseFormat = ais.getFormat();
			AudioFormat decodedFormat = new AudioFormat(
					AudioFormat.Encoding.PCM_SIGNED,
					baseFormat.getSampleRate(), 16, baseFormat.getChannels(),
					baseFormat.getChannels() * 2, baseFormat.getSampleRate(),
					false);
			AudioInputStream din = AudioSystem.getAudioInputStream(
					decodedFormat, ais);
			// Play now.
			rawplay(decodedFormat, din);

		} finally {
			try {
				ais.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	private void rawplay(AudioFormat targetFormat, AudioInputStream din)
			throws IOException, LineUnavailableException {
		byte[] data = new byte[4096];
		SourceDataLine line = getLine(targetFormat);
		if (line != null) {
			// Start
			line.start();
			int nBytesRead = 0, nBytesWritten = 0;
			while (nBytesRead != -1) {
				nBytesRead = din.read(data, 0, data.length);
				if (nBytesRead != -1)
					nBytesWritten = line.write(data, 0, nBytesRead);
			}
			// Stop
			line.drain();
			line.stop();
			line.close();
			din.close();
		}
	}

	private SourceDataLine getLine(AudioFormat audioFormat)
			throws LineUnavailableException {
		SourceDataLine res = null;
		DataLine.Info info = new DataLine.Info(SourceDataLine.class,
				audioFormat);
		res = (SourceDataLine) AudioSystem.getLine(info);
		res.open(audioFormat);
		return res;
	}

}
